package tool;

import java.io.BufferedReader;
import java.io.File;
import java.io.FileReader;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;

import model.ConfigModel;

import applet.energy.ImageCanvas;
import applet.molecule.Atom;

public class DataFileHandler {

	public static final String DATA_FOLDER = "/data";

	public static final String DATA_ORIGIN = "/origin";
	
	public static final String DATA_PARSED = "/parsed";

	/**
	 * parse configuration file "configuration.gz" from given file path 
	 * <code>filePath</code>
	 * 
	 * @param filePath the file path of configuration.gz
	 * 
	 * @return the configuration model 
	 * 
	 * @throws IOException if there is some IO exception occur
	 */
	public static ConfigModel parseDataFile(String filePath)
			throws Exception {
		BufferedReader reader = new BufferedReader(new FileReader(filePath));
		ConfigModel model = ConfigModel.parseConfigModel(reader);
		return model;
	}

	/**
	 * Check whether the format of the upload energy height file is valid, and
	 * delete temporary file after cached.
	 * 
	 * @param filePath the file path of the energy height file uploadeds
	 * 
	 * @return whether the format of the upload energy height file is valid
	 */
	public static boolean checkHTFileAndCache(String filePath) {
		try {
			float[][] data = parseHTFile(filePath);
			
			Cache.getInstance().put(
					filePath.substring(filePath.lastIndexOf('/') + 1), data);

			new File(filePath).delete();
			
			return true;
		} catch (Exception e) {
			new File(filePath).delete();
			
			return false;
		}
	}

	/**
	 * Parse energy height file.	<p/>
	 * 
	 * The format of the energy height file is like this:	<p/>
	 * 
	 * 0	0	15.8436491565605 (2D coordinates and the energy height 
	 * at the point)	<br/>
	 * 0	1	21.5770411420305	<br/>
	 * 0	2	30.6216194978141	<br/>
	 * ...	<br/>
	 * 0	40	34.1547747134908	<br/>
	 * 1	0	35.7551736308153	<br/>
	 * 1	1	38.9516172953959	<br/>
	 * ...	<br/>
	 * 1	40	41.9867124919404	<br/>
	 * 2	0	44.4248697878286	<br/>
	 * ...	<br/> 
	 * 40	39	64.5135922977227	<br/>
	 * 40	40	47.7323457030503	<br/>
	 * 
	 * @param filePath the path of the data file
	 * 
	 * @return 2D float array contains the coordinates and the energy height 
	 * 			at each point
	 * @throws Exception 
	 */
	private static float[][] parseHTFile(String filePath) throws Exception {
		BufferedReader reader = new BufferedReader(new FileReader(filePath));

		String line;
		String[] split;
		int x, y;
		float h;
		float[][] list = new float[ImageCanvas.POINT_NUM][ImageCanvas.POINT_NUM];
		while ((line = reader.readLine()) != null) {
			line = line.trim();
			if (line.length() == 0) {
				continue;
			}

			split = line.split("[\\s]+");

			x = Integer.parseInt(split[0]);
			y = Integer.parseInt(split[1]);
			h = Float.parseFloat(split[2]);

			list[ImageCanvas.POINT_NUM - y - 1][x] = h;
		}

		reader.close(); 
		return list;
	}

	/**
	 * Parse the atom data file.	<p/>
	 * 
	 * The atom data file is like this:	<p/>
	 * 
	 * 8	(the number of atoms)	<br/>
	 * O -35.815895 399.96198 -669.3866	(element, x coordinate, y z)	<br/>
	 * C -35.25986 401.15182 -669.9523	<br/>
	 * C -35.84752 401.48053 -671.3373	<br/>
	 * C -35.96277 400.32187 -672.34515	<br/>
	 * C -36.4701 400.75546 -673.73303	<br/>
	 * C -36.642956 399.58148 -674.7146	<br/>
	 * C -37.03109 399.93735 -676.16174	<br/>
	 * H -35.187313 399.62866 -668.76465	<br/>
	 * 
	 * @param dir the parent directory of the data file
	 * @param filename the name of the data file
	 * 
	 * @return a list of atoms
	 */
	public static List<Atom> parseAtomFile(String dir, String filename) {
		File file = new File(dir, filename);
		List<Atom> list = null;
		BufferedReader reader = null;
		try { 
			reader = new BufferedReader(new FileReader(file));

			String line;
			line = reader.readLine().trim();
			int num = Integer.parseInt(line);

			String[] split;
			String element;
			float x, y, z;
			list = new ArrayList<Atom>();
			for (int i = 0; i < num; i++) {
				line = reader.readLine().trim();
				if (line.length() == 0) {
					i--;
					continue;
				}

				split = line.split("[\\s]+");

				element = split[0];
				x = Float.parseFloat(split[1]);
				y = Float.parseFloat(split[2]);
				z = Float.parseFloat(split[3]);

				list.add(new Atom(element, x, y, z));
			}
			
			reader.close();
		} catch (IOException e) {
			// System.out.println("INFO: File " + file.getAbsolutePath() + " does not exist");
		}

		return list;
	}

	/**
	 * The main method for parsing configuration model data.
	 * 
	 * @param args the arguments list. the first argument is the configuration file
	 * 				"configuration.gz", and if the length of this list is 2, the 
	 * 				second argument is the destination folder, else the destination
	 * 				folder is current folder.
	 */ 
	public static void main(String[] args) {
		try {
			ConfigModel model = parseDataFile(args[0]);
			
			if(args.length > 1){
				model.store(args[1]);
			}else{
				File file = new File(args[0]);
				model.store(file.getParent());
			}
		} catch (Exception e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
	}
}
